/*
* ====================================================================
* Copyright (c) 2013-2014 Neudesic.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
* retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* This source file includes software written by Neudesic, LLC (http://www.neudesic.com).
*
* THIS SOFTWARE IS PROVIDED BY Neudesic, LLC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  FURTHER, IN NO EVENT SHALL
* Neudesic, LLC (THE AUTHOR) OR ANY CONTRIBUTORS BE LIABLE FOR ANY DAMAGES
* WHATSOEVER THAT ARE RELATED TO THE SOFTWARE [INCLUDING BUT NOT LIMITED TO,
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* SUCH AS LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION, HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)] EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
*
* ====================================================================
*/
#ifndef _DATAGRAMSOCKETCONTAINER_H_
#define _DATAGRAMSOCKETCONTAINER_H_

#include "socketcontainer.h"
#include <string>
#include <wrl.h>
#include <windows.storage.streams.h>
#include <windows.networking.sockets.h>
#include "winrtutils.h"

using ABI::Windows::Networking::IHostName;
using ABI::Windows::Foundation::IAsyncAction;
using ABI::Windows::Storage::Streams::IDataReader;
using ABI::Windows::Networking::Sockets::IDatagramSocket;
using ABI::Windows::Networking::Sockets::IDatagramSocketInformation;
using ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs;
using Microsoft::WRL::ComPtr;

namespace Neudesic {
	namespace Sockets {

		class DatagramSocketContainer : public SocketContainer<IDatagramSocket, IDatagramSocketInformation>, public IDatagramSocketContainer
		{
		public:
			DatagramSocketContainer(void);
			virtual ~DatagramSocketContainer(void);
		public:
#pragma region ISocketContainer
			HRESULT Close();
			HRESULT EventSelect(WSAEVENT hEventObject, long lNetworkEvents);
			HRESULT GetSocketName(struct sockaddr* name, int* namelen) const;
			HRESULT SetSocketOptions(int level, int optname, const char* optval, int optlen);
		protected:
#pragma endregion
		public:
			HRESULT BindSocket(const struct sockaddr* name);
			HRESULT ReceiveFrom(char *buf, int len, int flags, struct sockaddr *from, int *fromlen, LPDWORD lpNumberOfBytesRecvd);
			HRESULT SendTo(const char* buf, unsigned int len, int flags, const sockaddr* to, int tolen, UINT32* numberOfBytesSent);
		protected:
			HRESULT Bind(const ComPtr<IHostName>& hostName, const wchar_t* serviceName);
			HRESULT ConnectSocket(const ComPtr<IHostName>& hostName, const wchar_t* serviceName);
			void CreateSocket();
		private:
			HRESULT PrepareForMessages();
			HRESULT Send(const char* buf, unsigned int len, const ComPtr<IHostName>& hostName, const wchar_t* serviceName, UINT32* numberOfBytesSent);
		private:
			EventRegistrationToken messageReceivedToken;
			HostAndPortInformation bindHostAndPortInfo;
		};

	}
}
#endif